﻿using ff14bot.Behavior;
using ff14bot.Enums;
using ff14bot.Managers;
using System.Linq;
using TreeSharp;
using Magitek.Helpers;
using ff14bot;
using Action = TreeSharp.Action;
using ff14bot.Objects;

namespace Magitek.Rotations
{
    public class Summoner : Magitek
    {
        public override float PullRange { get { return WindowSettings.SummonerPullRange; } }
        public override ClassJobType[] Class { get { return new ClassJobType[] { ClassJobType.Summoner }; } }
        public override void OnPulse() { }
        #region Pulling & Resting
        protected override Composite CreatePull()
        {
            return Combat.CreatePull(25);
        }

        protected override Composite CreateRest()
        {
            return Extensions.DefaultRestBehavior(r => Core.Player.CurrentManaPercent);
        }
        #endregion
        #region Buffs // Mainly used for Grindbot etc...

        protected override Composite CreatePreCombatBuffs()
        {
            return new PrioritySelector(
                Extensions.SummonChocobo()
                );
        }

        protected override Composite CreateCombatBuffs()
        {
            return new PrioritySelector(
                new Decorator(r => WindowSettings.lastspellused == "Swiftcast", new ActionAlwaysSucceed()),

                Casting.Cast(r => "Aetherflow", r => !Core.Player.HasAura("Aetherflow"), r => Core.Player, r => 3, r => false),               
                Casting.Cast(r => "Raging Strikes", r => WindowSettings.SummonerUseBuffs && !HasDotsWithoutTimeLeft(), r => Core.Player, r => 3, r => false),      

                //   Dont save buffs.
                Casting.Cast(r => "Rouse", r => WindowSettings.SummonerUseBuffs && !WindowSettings.SummonerSaveBuffs && Core.Player.Pet != null && !Actionmanager.CanCast("Fester", Core.Player.CurrentTarget), r => Core.Player, r => 3, r => false),
                Casting.Cast(r => "Spur", r => WindowSettings.SummonerUseBuffs && !WindowSettings.SummonerSaveBuffs && Core.Player.Pet != null && !Actionmanager.CanCast("Fester", Core.Player.CurrentTarget), r => Core.Player, r => 3, r => false),
  
                //   Only Use Spur or Rouse if both of them are up.
                Casting.Cast(r => "Rouse", r => WindowSettings.SummonerUseBuffs && WindowSettings.SummonerSaveBuffs && Core.Player.Pet != null && (Actionmanager.CanCast("Spur", Core.Player) || Core.Player.Pet.HasAura("Spur")), r => Core.Player, r => 3, r => false),
                Casting.Cast(r => "Spur", r => WindowSettings.SummonerUseBuffs && WindowSettings.SummonerSaveBuffs && Core.Player.Pet != null && Core.Player.Pet.HasAura("Rouse"), r => Core.Player, r => 3, r => false),
 

                Casting.Cast(r => "Quelling Strikes", r => WindowSettings.SummonerUseBuffs && WindowSettings.SummonerUseQuellingStrikes, r => Core.Player, r => 3, r => false)

            );
        }

        #endregion
        #region Combat

        protected override Composite CreateHeal()
        {
            return new PrioritySelector(

                new Decorator(r => WindowSettings.SummonerLetMagitekControlPet, Extensions.PetFollow),

                Casting.Cast(r => "Resurrection", r => WindowSettings.SummonerSwiftcastRez && PartyHelper.Deadtarget != null && Actionmanager.CanCast("Resurrection", PartyHelper.Deadtarget) && Core.Player.HasAura("Swiftcast") && Core.Player.InCombat, r => PartyHelper.Deadtarget, r => 3, r => false),
        
                new Decorator(ret =>
                {
                    if (!WindowSettings.SummonerSwiftcastRez)
                        return false;

                    if (Core.Player.Pet != null && !WindowSettings.SummonerSwiftcastFlare)
                        return false;

                    if (Core.Player.HasAura("Swiftcast"))
                        return true;

                    return true;

                }, new PrioritySelector(
                    Casting.Cast(r => "Swiftcast", r => Core.Player.Pet == null, r => Core.Player, r => 4, r => false),
                    Casting.Cast(r => "Summon", r => Core.Player.Pet == null && WindowSettings.SummonerUseGaruda && Core.Player.HasAura("Swiftcast"), r => Core.Player, r => 4, r => false),
                    Casting.Cast(r => "Summon III", r => Core.Player.Pet == null && WindowSettings.SummonerUseIfrit && Core.Player.HasAura("Swiftcast"), r => Core.Player, r => 4, r => false),
                    Casting.Cast(r => "Summon II", r => Core.Player.Pet == null && WindowSettings.SummonerUseTitan && Core.Player.HasAura("Swiftcast"), r => Core.Player, r => 4, r => false)

                    )),

                Casting.Cast(r => "Summon", r => !Core.Player.InCombat && Core.Player.Pet == null && WindowSettings.SummonerUseGaruda && WindowSettings.lastspellused != "Summon", r => Core.Player, r => 4, r => false),
                Casting.Cast(r => "Summon III", r => !Core.Player.InCombat && Core.Player.Pet == null && WindowSettings.SummonerUseIfrit && WindowSettings.lastspellused != "Summon III", r => Core.Player, r => 4, r => false),
                Casting.Cast(r => "Summon II", r => !Core.Player.InCombat && Core.Player.Pet == null && WindowSettings.SummonerUseTitan && WindowSettings.lastspellused != "Summon II", r => Core.Player, r => 4, r => false),


                Casting.Cast(r => "Physick", r => Core.Player.CurrentHealthPercent <= WindowSettings.SummonerHealSelf, r => Core.Player, r => 3, r => false),
                Casting.Cast(r => "Physick", r => Core.Player.Pet != null && Core.Player.Pet.CurrentHealthPercent <= WindowSettings.SummonerHealPetPhysick, r => Core.Player.Pet, r => 3, r => false),
                Casting.Cast(r => "Sustain", r => Core.Player.Pet != null && Core.Player.Pet.CurrentHealthPercent <= WindowSettings.SummonerHealPetSustain && !Core.Player.Pet.HasAura("Sustain"), r => Core.Player.Pet, r => 3, r => false)
                );
        }

        #region Summoner Helpers
        public int MiasmaII()
        {
                return Extensions.UnfriendlyUnits.Count(u => !u.HasAura("Miasma II", true) && u.Location.Distance(Core.Player.Location) <= 5);
        }

        public int Bane()
        {
            return Extensions.UnfriendlyUnits.Count(u => !u.HasAura("Miasma", true) && !u.HasAura("Bio", true) && !u.HasAura("Bio II", true) && u.Location.Distance(Core.Player.CurrentTarget.Location) <= 8);
        }

        public bool HasDots(int TimeLeft)
        {
            if (Core.Player.CurrentTarget.HasAura("Bio", true, TimeLeft) &&
                Core.Player.CurrentTarget.HasAura("Bio II", true, TimeLeft) &&
                Core.Player.CurrentTarget.HasAura("Miasma", true, TimeLeft))
                return true;

            return false;
        }

        public bool HasDotsWithoutTimeLeft()
        {
            if (Core.Player.CurrentTarget.HasAura("Bio", true) &&
                Core.Player.CurrentTarget.HasAura("Bio II", true) &&
                Core.Player.CurrentTarget.HasAura("Miasma", true))
                return true;

            return false;
        }

        public Composite ShadowFlare()
        {
            return new PrioritySelector(

                
                //   Swiftcast Shadow Flare
                new Decorator(r =>

                    WindowSettings.SummonerSwiftcastFlare
                    && WindowSettings.SummonerSingleTargetFlare
                    && Actionmanager.HasSpell("Shadow Flare") 
                    && !Core.Player.HasAura("Shadow Flare") 
					&& Actionmanager.CanCast("Swiftcast", Core.Player),

                    new Sequence(                  
                        Casting.Cast(r => "Swiftcast", r => true, r => Core.Player, r => 4, r => false),
                        new Action(r => WindowSettings.lastspellused = "Shadow Flare"),
                        new Sleep(2000),
                        new Action(r => Actionmanager.DoActionLocation("Shadow Flare", Core.Player.CurrentTarget.Location)))),

                new Decorator(r => Core.Player.Pet != null && WindowSettings.SummonerSwiftcastFlare && Actionmanager.CanCast("Swiftcast", Core.Player), new ActionAlwaysSucceed()), 


                //   Normal cast Shadow Flare
                new Decorator(r =>
                Actionmanager.HasSpell("Shadow Flare")
                && WindowSettings.lastspellused != "Shadow Flare"
                && !Extensions.DoubleCastPreventionDict.Contains(Core.Player.CurrentTarget, "Shadow Flare")
                && HasDots(3000)
                && WindowSettings.SummonerUseFlare
                && WindowSettings.SummonerUseAOE
                && !Core.Player.HasAura("Shadow Flare")
                && ((!Core.Player.HasAura("Shadow Flare") && WindowSettings.SummonerSingleTargetFlare) || (Extensions.EnemiesNearTarget(5) >= WindowSettings.TargetsToAOE && !WindowSettings._dontaoeList.Contains(Core.Player.CurrentTarget.Name))),
 
                new Sequence(
                    new Action(r => WindowSettings.lastspellused = "Shadow Flare"),
                    new Sleep(500),
                    new Action(r => Actionmanager.DoActionLocation("Shadow Flare", Core.Player.CurrentTarget.Location)),
                    new Action(r => Extensions.UpdateDoubleCastDict("Shadow Flare", Core.Player.CurrentTarget)))));
        }
        #endregion

        protected override Composite CreateCombat()
        {
            return new PrioritySelector(ctx => Core.Player.CurrentTarget,
                new Decorator(ctx => ctx != null,
                new PrioritySelector(
                new Decorator(ctx => ctx != null && BotManager.Current.IsAutonomous,
                    new PrioritySelector(
                        CommonBehaviors.MoveToLos(ctx => ctx as GameObject),
                        CommonBehaviors.MoveAndStop(ctx => (ctx as GameObject).Location, ctx => 24 + (ctx as GameObject).CombatReach, true, "Moving to unit")
						)
					),
                PartyHelper.AcquireTargetInformation(),
                #region Pet Casting
 
                Casting.Cast(r => "Resurrection", r => WindowSettings.SummonerSwiftcastRez && WindowSettings.lastspellused == "Swiftcast" && PartyHelper.Deadtarget != null && Actionmanager.CanCast("Resurrection", PartyHelper.Deadtarget) && Core.Player.HasAura("Swiftcast") && Core.Player.InCombat, r => PartyHelper.Deadtarget, r => 3, r => false),
                Casting.Cast(r => "Enkindle", r => WindowSettings.lastspellused != "Swiftcast" && Core.Player.Pet != null && Core.Player.Pet.HasAura("Rouse") && Core.Player.Pet.HasAura("Spur"), r => Core.Player.CurrentTarget, r => 3, r => false),

                 new Action(ret =>
                 {
                     if (Core.Player.Pet != null && Core.Player.Pet.Name == "Garuda-Egi" && WindowSettings.SummonerLetMagitekControlPet && Pet.PetMode == PetMode.Sic)
                     {
                         Pet.DoAction("Obey", Core.Player.Pet);
                     }

                     if ((Core.Player.Pet != null && !WindowSettings.SummonerLetMagitekControlPet && Pet.PetMode == PetMode.Obey) || (Pet.PetMode == PetMode.Obey && Core.Player.Pet.Name != "Garuda-Egi"))
                     {
                         Pet.DoAction("Sic", Core.Player.Pet);
                     }

                     return RunStatus.Failure;

                 }),

                Combat.DoPVP(),

                Casting.PetCast(r => Core.Player.CurrentTarget, r => "Contagion", r => WindowSettings.SummonerLetMagitekControlPet && !Core.Player.CurrentTarget.HasAura("Miasma", true, 7000) && !WindowSettings.SummonerContagionWithPotion),
                Casting.PetCast(r => Core.Player.CurrentTarget, r => "Contagion", r => WindowSettings.SummonerLetMagitekControlPet && !Core.Player.CurrentTarget.HasAura("Miasma", true, 7000) && WindowSettings.SummonerContagionWithPotion && Core.Player.HasAura("Poison", true)),
                Casting.PetCast(r => Core.Player.CurrentTarget, r => "Aerial Slash", r => WindowSettings.SummonerLetMagitekControlPet && (Extensions.EnemiesNearTarget(5) >= 3 || WindowSettings.SummonerGarudaUseAerialOnSingle)),
                Casting.PetCast(r => Core.Player.CurrentTarget, r => "Shockwave", r => WindowSettings.SummonerLetMagitekControlPet),
                Casting.PetCast(r => Core.Player.CurrentTarget, r => "Wind Blade", r => WindowSettings.SummonerLetMagitekControlPet),

                new Decorator(r => WindowSettings.SummonerUsePotentPoisoningPotion && Core.Player.CurrentTarget.Location.Distance(Core.Player.Location) < 5  && Items.CanUseItem("Potent Poisoning Potion") && HasDots(15000), new Action(r => Items.Use("Potent Poisoning Potion", false))),
                #endregion
                new Decorator(r => Core.Player.IsCasting, new ActionAlwaysSucceed()),

                ShadowFlare(),

                Casting.Cast(r => "Miasma II", r => WindowSettings.lastspellused == "Enkindle" && Core.Player.CurrentTarget.Location.Distance(Core.Player.Location) <= 5, r => Core.Player, r => 2, r => true),

                Casting.Cast(r => "Fester", r => WindowSettings.lastspellused == "Ruin II" && (Core.Player.CurrentTarget.HasAura("Miasma", true) && Core.Player.CurrentTarget.HasAura("Bio II", true) && Core.Player.CurrentTarget.HasAura("Bio", true))
                && (Core.Player.HasAura("Aetherflow")), r => Core.Player.CurrentTarget, r => 2, r => false),

                Casting.Cast(r => "Bio II", r => WindowSettings.lastspellused != "Swiftcast" && !Core.Player.CurrentTarget.HasAura("Bio II", true, 3000) && (Core.Player.CurrentTarget as BattleCharacter).CurrentHealth > WindowSettings.SummonerUSeDOTsHealth, r => Core.Player.CurrentTarget, r => 2, r => true),
                Casting.Cast(r => "Miasma", r => WindowSettings.lastspellused != "Swiftcast" && !Core.Player.CurrentTarget.HasAura("Miasma", true, 3000) && (Core.Player.CurrentTarget as BattleCharacter).CurrentHealth > WindowSettings.SummonerUSeDOTsHealth, r => Core.Player.CurrentTarget, r => 2, r => true),
                Casting.Cast(r => "Bio", r => WindowSettings.lastspellused != "Swiftcast" && !Core.Player.CurrentTarget.HasAura("Bio", true, 3000) && (Core.Player.CurrentTarget as BattleCharacter).CurrentHealth > WindowSettings.SummonerUSeDOTsHealth, r => Core.Player.CurrentTarget, r => 2, r => true),
 
                Casting.Cast(r => "Summon", r => Core.Player.Pet == null && WindowSettings.SummonerUseGaruda && Core.Player.HasAura("Swiftcast"), r => Core.Player, r => 4, r => false),
                Casting.Cast(r => "Summon III", r => Core.Player.Pet == null && WindowSettings.SummonerUseIfrit && Core.Player.HasAura("Swiftcast"), r => Core.Player, r => 4, r => false),
                Casting.Cast(r => "Summon II", r => Core.Player.Pet == null && WindowSettings.SummonerUseTitan && Core.Player.HasAura("Swiftcast"), r => Core.Player, r => 4, r => false),

                Casting.Cast(r => "Aetherflow", r => !Core.Player.HasAura("Aetherflow"), r => Core.Player, r => 3, r => false),
                Casting.Cast(r => "Energy Drain", r => Core.Player.HasAura("Aetherflow") && Core.Player.CurrentManaPercent <= WindowSettings.SummonerEnergyDrainMana, r => Core.Player.CurrentTarget, r => 3, r => false),
                Casting.Cast(r => "Eye for an Eye", r => PartyHelper.Eyeforaneyetarget != null && WindowSettings.SummonerUseEyeforanEye && PartyHelper.Eyeforaneyetarget.CurrentHealthPercent <= 60, r => PartyHelper.Eyeforaneyetarget, r => 3), Casting.Cast(r => "Virus", r => WindowSettings.SummonerUseVirus && !Core.Player.CurrentTarget.HasAura("Virus"), r => Core.Player.CurrentTarget, r => 3, r => true),
               
                Casting.Cast(r => "Bane", r => Bane() >= WindowSettings.TargetsToAOE && WindowSettings.SummonerUseAOE && !WindowSettings._dontaoeList.Contains(Core.Player.CurrentTarget.Name) && HasDots(15000), r => Core.Player.CurrentTarget, r => 2, r => false),  
                Casting.Cast(r => "Miasma II", r => WindowSettings.SummonerUseMiasmaII && WindowSettings.SummonerUseAOE && (MiasmaII() >= WindowSettings.TargetsToAOE || (!Core.Player.CurrentTarget.HasAura("Miasma II", true) && Core.Player.CurrentTarget.Location.Distance(Core.Player.Location) <= 5)), r => Core.Player, r => 3, r => true),
                Casting.Cast(r => "Ruin II", r => WindowSettings.lastspellused != "Fester" && Actionmanager.CanCast("Fester", Core.Player.CurrentTarget) && HasDots(3000)
                && (Core.Player.HasAura("Aetherflow")), r => Core.Player.CurrentTarget, r => 2, r => false),

                new Decorator(r =>
                {
                    if (PartyManager.IsInParty && PartyManager.VisibleMembers.FirstOrDefault(u => u.Name == Core.Player.Name).SyncdLevel < 50)
                        return true;

                    if (Core.Player.CurrentTarget.CurrentHealth <= WindowSettings.SummonerUSeDOTsHealth)
                        return true;

                    if (Core.Player.CurrentTarget.CurrentHealthPercent >= WindowSettings.SummonerUSeDOTsHealth)

                    if (Core.Player.ClassLevel < 50)
                        return true;

                    if (HasDots(3000))
                        return true;

                    return false;

                }, new PrioritySelector(

                Casting.Cast(r => "Ruin", r => !Core.Player.IsCasting, r => Core.Player.CurrentTarget, r => 3, r => false),
                Casting.Cast(r => "Ruin II", r => !Core.Player.IsCasting, r => Core.Player.CurrentTarget, r => 3, r => false)))

                )));
        }
        #endregion
    }
}